/*
 This file is part of BTStracker
		
    BTStracker is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    BTStracker is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.	
	author: azbest.pro (azbest.pro@gmail.com)
*/
package pl.vdl.azbest.mremote.com;

import gnu.io.SerialPort;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import static pl.vdl.azbest.mremote.com.CommState.*;
import pl.vdl.azbest.annotations.Level;
import pl.vdl.azbest.annotations.TODO;
import pl.vdl.azbest.log.LoggingTheGathering;
import pl.vdl.azbest.mremote.gui.GUIFacade;
import pl.vdl.azbest.mremote.mob.ATOutputStream;

@TODO(dateAssigned = "08-04-2008", level = Level.CRITICAL, target = "1.Add state pattern to proect<br>", done = "")
/** Connecting to device, executing commands and receiving anwsers. */
public class CConnect {
	CState state;

	CState sConnected;

	CState sDisconnected;

	CState sConnecting;

	CState sCommunicate;
    private ATOutputStream MRStream =  ATOutputStream.getInstance();
	private volatile static CConnect instance;

	private List<CommObserver> olist = new ArrayList<CommObserver>();

	private CommState info;

	private InputStream portInputStream;

	private OutputStream portOutputstream;

	private SerialPort sPort;

	private SerialPortReader serialPortReader;

	

	private Logger logger = Logger.getLogger(getClass().getName());
	{
		LoggingTheGathering.addPath(getClass().getName());
	}

	public InputStream getPortInputStream() {
		return portInputStream;
	}

	public void setPortInputStream(InputStream portInputStream) {
		this.portInputStream = portInputStream;
	}

	public OutputStream getPortOutputstream() {
		return portOutputstream;
	}

	public void setPortOutputstream(OutputStream portOutputstream) {
		this.portOutputstream = portOutputstream;
	}

	public synchronized static CConnect getInstance() {
		if (instance == null) {
			instance = new CConnect();
			return instance;
		} else {
			return instance;
		}
	}

	private CConnect() {
		sConnected = new CSConnected(this);
		sCommunicate = new CSCommunicate(this);
		sConnecting = new CSConnecting(this);
		sDisconnected = new CSDisconnected(this);
		state = sDisconnected;

		logger.info("COMM connector initilized.");
	}

	public void connect() {
		logger.info("Conection signal to connect");
		state.connect();
	}

	public void disconnect() {
		state.disconnect();
	}

	public void openCommunication() {
		state.openCommunication();
	}

	public void closeCommunication() {
		state.closeCommunication();
	}

	public CState getState() {
		return state;
	}

	public void setState(CommState info, String txt, CState... state) {
		info.setGUITxt(txt);
		this.info = info;
		if (state.length > 1) {
			throw new IllegalArgumentException("Cannot pass such argument. ");
		}
		if (state.length > 0) {
			this.state = state[0];
		}
		notifyObservers();
	}

	public void registerObserver(CommObserver o) {
		this.olist.add(o);
	}

	public void removeObserver(CommObserver o) {
		this.olist.remove(o);
	}

	public void notifyObservers() {
		for (CommObserver co : this.olist) {
			co.update(info);
		}
	}

	public void perform() {
		logger.info("Performing connection");
		state.perform();
	}

	public SerialPort getSPort() {
		return sPort;
	}

	public void setSPort(SerialPort port) {
		sPort = port;
	}

	public SerialPortReader getSerialPortReader() {
		return serialPortReader;
	}

	public void setSerialPortReader(SerialPortReader serialPortReader) {
		this.serialPortReader = serialPortReader;
	}



	public void write(String line) {
		logger.info("Got writing cmd command.");
		
		state.write(line);
	}

	public ATOutputStream getMRStream() {
		return MRStream;
	}

	public void setMRStream(ATOutputStream stream) {
		MRStream = stream;
	}

}
